package com.kob.matchingsystem.service.impl.utils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;

@Component
public class MatchingPool extends Thread{
    //存所有user
    private static List<Player> players=new ArrayList<>();//传参线程，匹配线程都要访问player，加锁
    //定义一个锁
    private ReentrantLock lock=new ReentrantLock();
    private static RestTemplate restTemplate;
    private final static String startGameUrl="http://127.0.0.1:3000/pk/start/game/";

    @Autowired
    public void setRestTemplate(RestTemplate restTemplate){
        MatchingPool.restTemplate=restTemplate;
    }

    //添加一个玩家
    public void addPlayer(Integer userId,Integer rating,Integer botId){
        lock.lock();
        try {
            players.add(new Player(userId,rating,botId,0));
        }finally {
            lock.unlock();
        }
    }

    //删除一名玩家
    public void removePlayer(Integer userId){
        lock.lock();
        try {
            List<Player> newPlayers=new ArrayList<>();
            for (Player player:players){
                if(!player.getUserId().equals(userId)){
                    newPlayers.add(player);//把没有必要删除的玩家加到新池子内，新池子作为下次的玩家池子
                }
            }

            players=newPlayers;
        }finally {
            lock.unlock();
        }
    }

    //把所有等待玩家等待时间加1
    private void increasingWaitingTime(){
        for (Player player:players){
            player.setWaitingTime(player.getWaitingTime()+1);
        }
    }

    //判断两个玩家是否匹配
    private boolean checkMatched(Player a,Player b){
        int ratingDelta=Math.abs(a.getRating()-b.getRating());//分差
        int waitingTime=Math.min(a.getWaitingTime(),b.getWaitingTime());//二者都愿意情况下：满足二者要求最低的那个就行
        return ratingDelta<=waitingTime*10;//等待时间越长，可接受分差越大
    }

    //返回匹配结果
    private void sendResult(Player a,Player b){
        System.out.println("send result: "+a+" "+b);
        MultiValueMap<String,String> data=new LinkedMultiValueMap<>();
        data.add("a_id",a.getUserId().toString());
        data.add("a_bot_id",a.getBotId().toString());
        data.add("b_bot_id",b.getBotId().toString());
        data.add("b_id",b.getUserId().toString());
        restTemplate.postForObject(startGameUrl,data,String.class);
    }

    //尝试匹配所有玩家
    private void matchPlayers(){
        System.out.println("match players: "+players.toString());
        //布尔数组存储哪些玩家已经找到对象了
        boolean[] used=new boolean[players.size()];
        //先尝试匹配等待时间长的，防止饥饿
        for (int i=0;i<players.size();i++){
            if(used[i])continue;
            for (int j=i+1;j<players.size();j++){
                if (used[j])continue;
                Player a=players.get(i),b=players.get(j);
                if (checkMatched(a,b)){//如果可以匹配
                    used[i]=used[j]=true;
                    sendResult(a,b);
                    break;
                }
            }
        }

        //匹配成功以后，把用过的玩家删掉
        List<Player> newPlayers=new ArrayList<>();
        for (int i=0;i<players.size();i++){
            if(!used[i]){
                newPlayers.add(players.get(i));
            }
        }
        players=newPlayers;
    }

    @Override
    public void run() {
        while (true){
            try {
                Thread.sleep(1000);
                lock.lock();
                try {
                    increasingWaitingTime();
                    matchPlayers();
                }finally {
                    lock.unlock();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
                break;
            }
        }
    }
}
